/*
 * UISwitchListener.java
 * 
 * last update: 14.01.2010 by Stefan Saru
 * 
 * author:	Alec(alecu@kermit.cs.pub.ro)
 *
 * Obs: N/A
 */

package ide;

import javax.swing.plaf.basic.*;
import javax.swing.text.*;
import java.awt.*;
import javax.swing.DebugGraphics;
import javax.swing.event.DocumentListener;
import javax.swing.event.DocumentEvent;

/**
 * The highligted view of a verilog piece
 */

class VerilogPlainView
extends PlainView implements DocumentListener
{

	VerilogTextArea daddy;
	ColorProvider cp;
	VerilogScanner vs;

	/**
	 * Here each line has one byte for its 'style'
	 * (for now the sole purpose is to tell whether this
	 * line is or not inside a multi-line comment: if we are inside a comment,
	 * the corresponding byte will be 1).
	 * *NOTE* The corresponding byte for line n is at
	 * index n-1.
	 */
	byte lineTypes[];

	/**
	 * The amount with which lineTypes will grow
	 * when nedded.
	 */
	static final byte lineTypesIncrement = 20;

	VerilogPlainView (Element elem, VerilogTextArea daddy) {
		super(elem);
		this.daddy = daddy;
		System.out.println("creating new VerilogPlainView for element " + elem);
		cp = new DefaultColorProvider();
		vs = new VerilogScanner();
		lineTypes = new byte[daddy.getLineCount() + lineTypesIncrement];
		getDocument().addDocumentListener(this);
	}


	/**
	 * the core of the syntax highlighting:
	 */
	protected void drawLine(int lineIndex, Graphics g, int x, int y) {

		Document doc = getDocument();
		Segment line = getLineBuffer();
		byte lineType = 0;
		//System.out.println("drawing line " + lineIndex);
		try {
			int start = daddy.getLineStartOffset(lineIndex),
			len = daddy.getLineEndOffset(lineIndex) - start -1;
			if (len < 1) {
				lineTypes[lineIndex+1] = lineTypes[lineIndex];
				return;
			}
			//cand se intampla asta Power?
			//Alec->cand am o line goala ca shi capu' tau ! 
			doc.getText(start, len, line);
			vs.init(line);
			switch (lineTypes[lineIndex]) {
			case 1:
				//System.out.println("inside comment");
				if (!vs.scanCommentEnd())
					lineType = 1;
				//System.out.println("stop: " + vs.stop + " c: " + vs.c); 
				g.setColor(cp.getColor(VerilogScanner.tokMLComm));
				line.count = vs.tokLen;
				x = Utilities.drawTabbedText(line, x, y, g,
						this, line.offset); //flushrest
						line.offset += vs.tokLen;
						if (vs.noMoreTokens())
							break;
			default:
				//System.out.println("outside comment");
				Color lastColor = null, curColor = null;
				line.count = 0;
				while(vs.getToken()) {
					curColor = cp.getColor(vs.tokType);
					if (vs.tokType == VerilogScanner.tokMLComm &&
							vs.openComment) {
						//System.out.println("multiline comm start: " );
						lineType = 1;
					}
					if (lastColor == null)
						lastColor = curColor;
					if (curColor != lastColor) {
						g.setColor(lastColor);
						x = Utilities.drawTabbedText(line, x, y, g, this, line.offset);
						/*System.out.println("chunk: \"" +
                           (new String(line.array, line.offset, line.count)) +
                           "\"");*/
						lastColor = curColor;
						line.offset += line.count;
						line.count = 0;
					}
					line.count += vs.tokLen;
				}
				g.setColor(lastColor);
				Utilities.drawTabbedText(line, x, y, g, this, line.offset); //flush rest
				/*System.out.println("last chunk: \"" +
                           (new String(line.array, line.offset, line.count)) +
                           "\"");*/
			}

			/*System.out.println("now drawing: " + (new
        String(line.array, line.offset, line.count)));*/
		} catch (BadLocationException ex) {
			throw new Error(ex.getMessage() + ":" + ex.offsetRequested());
		}

		if (lineType != lineTypes[lineIndex + 1]) {
			//we need to update all the lines below us !
			lineTypes[lineIndex + 1] = lineType;
			Dimension d = daddy.getSize();
			daddy.repaint(0, y + daddy.getRowHeight(), d.width, d.height);
		}
		//daddy.setDebugGraphicsOptions(DebugGraphics.FLASH_OPTION);

	}

	//////////////////////////////////
	// DocumentListener implementation
	//////////////////////////////////

	public void changedUpdate(DocumentEvent e) {}

	/**
	 * this will ensure that  lineTypes vector is long enough to
	 * keep us out of trouble.
	 */
	public void insertUpdate(DocumentEvent e) {
		int count = daddy.getLineCount() + 1; //the first byte is for line no. -1
		int length = lineTypes.length;
		if (count >=  length) {
			int amount = lineTypesIncrement;
			while (count >= length + amount)
				amount += lineTypes.length;
			byte tmp[] = new byte[lineTypes.length + amount];
			System.arraycopy(lineTypes, 0, tmp, 0, length);
			lineTypes = tmp;
		}
	}

	public void removeUpdate(DocumentEvent e) {}
}